package com.seek.service.imp;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.seek.authcheck.constants.AuthConstant;
import com.seek.authcheck.constants.AuthProductEnum;
import com.seek.authcheck.constants.CertCardConstant;
import com.seek.authcheck.constants.NoticeConstant;
import com.seek.cache.CacheUtil;
import com.seek.constants.ApiParamsConstant;
import com.seek.constants.RedisCustomerConstant;
import com.seek.model.authcheck.CertCardAuthModel;
import com.seek.model.entity.TAuthMetric;
import com.seek.model.entity.TBizFlow;
import com.seek.model.entity.TCustomer;
import com.seek.model.entity.TCustomerCertify;
import com.seek.service.AuthMetricService;
import com.seek.service.BaseAuthCheckService;
import com.seek.service.CustomerCertifyService;
import com.seek.service.CustomerService;
import com.seek.service.BizFlowService;
import com.seek.service.RegionInfoService;
import com.seek.util.Base64Util;
import com.seek.util.DateUtil;
import com.seek.util.Push2SingleUtil;
import com.seek.util.UUIDUtil;
import com.seek.util.UpOtherImgToUpyun;
import com.seek.util.authcheck.AuthCheckUtils;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by weh on 2017/7/2.
 */
@Service(value = "certCardAuthCheck")
public class CertCardAuthCheckImpl implements BaseAuthCheckService {

  private static final Logger logger = LoggerFactory.getLogger(CertCardAuthCheckImpl.class);
  @Resource
  private BizFlowService bizFlowService;

  @Resource
  private CustomerService customerService;

  @Resource
  private AuthMetricService authMetricService;
  @Resource
  private CustomerCertifyService customerCertifyService;

  @Resource
  private RegionInfoService regionInfoService;

  @Resource
  private Push2SingleUtil push2SingleUtil;

  @Override
  @Transactional
  public void autoCheck(JSONObject json) {

    File img1 = new File(UUIDUtil.getUUID()+CertCardConstant.CERT_IMG_EXT);
    File img2 = new File(UUIDUtil.getUUID()+CertCardConstant.CERT_IMG_EXT);
    File img3 = new File(UUIDUtil.getUUID()+CertCardConstant.CERT_IMG_EXT);

    try {
      String bizNo = json.getString(NoticeConstant.PARTNER_ORDER_ID);

      boolean checkResult = false;

      //查询流水

      Map<String, Object> queryMap = new HashMap<>();
      queryMap.put("bizNo", bizNo);
      List<TBizFlow> bizFlows = bizFlowService.getBizFlowByParams(queryMap);
      if (CollectionUtils.isNotEmpty(bizFlows) && bizFlows.size() == 1) {

        TBizFlow bizFlow = bizFlows.get(0);
        String flowStatus = bizFlow.getStatus();
        int deleted = bizFlow.getDeleted();
        if (deleted == 1) {
          logger.warn("查询到流水号{}已失效", bizNo);
          bizFlowService.updateBizFlow(
              "update t_biz_flow set status = ? ,modify_time= now() where biz_no = ?",
              new Object[]{1, bizNo});
          return;
        }
        if (StringUtils.isNotEmpty(flowStatus) && StringUtils.equals(flowStatus, "1")) {
          logger.warn("查询到流水号{}已经调用成功，无需再次处理", bizNo);
          return;
        }
//        logger.info("更新流水.....{}", bizNo);

        //更新流水
        String updateBizFlowSql = "update t_biz_flow set status = ? ,modify_time= now() where biz_no = ? and deleted = ?";
        bizFlowService.updateBizFlow(updateBizFlowSql, new Object[]{"1", bizFlow.getBizNo(), 0});
        Map<String, Object> cacheData = new HashMap<>();
        TCustomer customer = null;
//        logger.info("获取客户信息.....");

        String queryCustSql = "select * from t_customer where id = ? and company_id = ?";
        List<TCustomer> customers = customerService
            .findBySql(queryCustSql, bizFlow.getCustomerId(), bizFlow.getCompanyId());
        if (CollectionUtils.isNotEmpty(customers) && customers.size() == 1) {
          customer = customers.get(0);
          customer.setStatus(1);
          cacheData.put("status",1);
        } else {
          logger.error("没有查询到客户号为{}的客户信息", bizFlow.getCustomerId());
          return;
        }


        TCustomerCertify customerCertify = new TCustomerCertify();

        customerCertify.setCustomerId(bizFlow.getCustomerId());
        customerCertify.setCompanyId(bizFlow.getCompanyId());
        customerCertify.setAuditTime(new Date());
        String creationTime = json.getString(NoticeConstant.CREATION_TIME);
        if (StringUtils.length(creationTime) == StringUtils
            .length(DateUtil.DATE_FORMAT_SHORT_YMDHMS)) {
          customerCertify.setSubmitTime(
              DateUtil.getDateByString(creationTime, DateUtil.DATE_FORMAT_SHORT_YMDHMS));
        } else {
          customerCertify.setSubmitTime(new Date());
        }
        String gpsKey = "GPS#" + bizNo;
        String gpsInfo = CacheUtil.getRedisData(gpsKey);
        if (StringUtils.isNotEmpty(gpsInfo)) {
          JSONObject gpsJson = (JSONObject) JSON.parse(gpsInfo);
          customerCertify.setRegCity(gpsJson.getString(ApiParamsConstant.GPS_CITY));
          customerCertify.setRegAddress(gpsJson.getString(ApiParamsConstant.GPS_ADDR));
        } else {
          logger
              .warn("没有查询到流水号为{},用户id为{}的gps身份认证信息！", bizFlow.getBizNo(), bizFlow.getCustomerId());
        }

        if (StringUtils
            .equals(json.getString(CertCardConstant.VERIFY_STATUS), CertCardConstant.VERIFY_SUCCESS)
            && StringUtils.equals(json.getString(CertCardConstant.AUTH_RESULT),
            CertCardConstant.AUTH_CHECK_SUCCESS)) {

//          logger.info("获取规则.....");
          // 获取规则
          Map<String, Object> paramsMap = new HashMap<>();
          paramsMap.put("authProduct", AuthProductEnum.CERTCARD.getProductCode().toUpperCase());
          paramsMap.put("companyId", bizFlow.getCompanyId());
          List<TAuthMetric> authMetrics = authMetricService.queryAuthMetricBySql(paramsMap);
//          logger.info("获取规则结果.....,{}", JSON.toJSONString(authMetrics));
          CertCardAuthModel certCardAuthModel = createCertCardAuthModel(json);
//          logger.info("创建认证模型.....{}", JSON.toJSONString(certCardAuthModel));

//          logger.info("开始认证.....");
          getCertCardAuthResult(certCardAuthModel, authMetrics);
          logger.info("认证结果.....{}", JSON.toJSONString(certCardAuthModel));

          customerCertify.setCardValid(json.getString(CertCardConstant.VALIDITY_PERIOD));
          //设置客户基本信息
          setCustomerProp(customer, json, certCardAuthModel);
          logger.info("更新客户状态....{}", JSON.toJSONString(customer));
          //认证成功
          if (certCardAuthModel.isAgeCheck() && certCardAuthModel.isAreaCheck()) {
            logger.info("{}认证成功！",customer.getId());
            //upload file ...
            String base64Img1 = json.getString(CertCardConstant.IDCARD_FRONT_PHOTO);
            String base64Img2 = json.getString(CertCardConstant.IDCARD_BACK_PHOTO);
            String base64Img3 = json.getString(CertCardConstant.IDCARD_PORTRAIT_PHOTO);
            customer.setCertificationStatus(AuthConstant.AUTH_SUCCESS);
            FileUtils.writeByteArrayToFile(img1,Base64Util.getFromBase64New(base64Img1));
            FileUtils.writeByteArrayToFile(img2,Base64Util.getFromBase64New(base64Img2));
            FileUtils.writeByteArrayToFile(img3,Base64Util.getFromBase64New(base64Img3));

            String img1Url = UpOtherImgToUpyun.writeFile(img1);
            String img2Url = UpOtherImgToUpyun.writeFile(img2);
            String img3Url = UpOtherImgToUpyun.writeFile(img3);

            customerCertify.setImg1(img1Url);
            customerCertify.setImg2(img2Url);
            customerCertify.setImg3(img3Url);

            customerCertify
                .setCardCity(regionInfoService.getCityByCardNo(customer.getCardNumber()));
            customerCertify.setAuditStatus(1);
            cacheData.put(RedisCustomerConstant.CERT_STATUS, AuthConstant.AUTH_SUCCESS);
            cacheData.put(RedisCustomerConstant.CUST_NO, customer.getCardNumber());
            cacheData.put(RedisCustomerConstant.CUST_NAME, customer.getName());
            checkResult = true;

          } else {
            customer.setCertificationStatus(AuthConstant.AUTH_FAIL);
            cacheData.put(RedisCustomerConstant.CERT_STATUS, AuthConstant.AUTH_FAIL);
            customerCertify.setAuditStatus(3);
            customerCertify.setAuditRemark(certCardAuthModel.getCheckMsg());
          }
        } else {
          customer.setCertificationStatus(AuthConstant.AUTH_FAIL);
          String failReason = json.getString(CertCardConstant.FAIL_REASON);
          cacheData.put(RedisCustomerConstant.CERT_STATUS, AuthConstant.AUTH_FAIL);
          customerCertify.setAuditStatus(2);
          customerCertify.setAuditRemark(StringUtils.isNotEmpty(failReason)? failReason : "第三方机构认证失败");
          logger.warn("第三方机构认证失败");
        }
//        logger.info("添加认证信息....{}", JSON.toJSONString(customerCertify));

        String delCertifySql = "delete from t_customer_certify where company_id = ? and customer_id = ?";
        customerCertifyService.executeUpdate(delCertifySql,
            new Object[]{bizFlow.getCompanyId(), bizFlow.getCustomerId()});
        customerCertifyService.save(customerCertify);

//        logger.info("更新客户信息....{}", JSON.toJSONString(customer));
        customerService.update(customer);
        if (checkResult) {
          push2SingleUtil
              .push2Single(Push2SingleUtil.TYPE_OF_CERTIFY_SUC, customer.getClientId());

        } else {
          push2SingleUtil
              .push2Single(Push2SingleUtil.TYPE_OF_CERTIFY_FAIL, customer.getClientId());
        }

        if (MapUtils.isNotEmpty(cacheData)) {
          String token = CacheUtil
              .getRedisData(RedisCustomerConstant.CUST_KEY_PREFIX + bizFlow.getCustomerId());
          if (StringUtils.isNotEmpty(token)) {
            CacheUtil.refreshCustRedis(token, cacheData);
          }
        }
        CacheUtil.delRedisData("GPS#" + bizNo);
      } else {
        logger.error("没有查询到{}的流水信息", bizNo);
      }
    } catch (Exception e) {
      e.printStackTrace();
      logger.error("身份认证自动认证出错, 错误信息:{}", e.getMessage());

    }finally {
      try {
        FileUtils.forceDelete(img1);
        FileUtils.forceDelete(img2);
        FileUtils.forceDelete(img3);
      } catch (IOException e) {
      }
    }

  }

  private void setCustomerProp(TCustomer customer, JSONObject json,
      CertCardAuthModel certCardAuthModel) {
    customer.setName(json.getString(CertCardConstant.ID_NAME));
    customer.setCardNumber(json.getString(CertCardConstant.ID_NUMBER));
    String birth = json.getString(CertCardConstant.BIRTHDAY);
    customer.setBirthday(new java.sql.Date(DateUtil.dateFormat(birth, "yyyy.MM.dd").getTime()));
    customer.setSex(Integer.valueOf(certCardAuthModel.getGender()));
    customer.setAge(Integer.valueOf(certCardAuthModel.getAge()));
  }


  /**
   * 创建身份证认证模型
   */
  private CertCardAuthModel createCertCardAuthModel(JSONObject reqObject) {

    CertCardAuthModel certCardAuthModel = new CertCardAuthModel();
    certCardAuthModel.setAge(reqObject.getString(CertCardConstant.AGE));
    certCardAuthModel
        .setAreaCode(StringUtils.substring(reqObject.getString(CertCardConstant.ID_NUMBER), 0, 2));
    certCardAuthModel
        .setGender(
            StringUtils.equals(reqObject.getString(CertCardConstant.GENDER), "男") ? "1" : "2");
    return certCardAuthModel;

  }

  /**
   * 身份证准入认证
   */
  private void getCertCardAuthResult(CertCardAuthModel model, List<TAuthMetric> authMetrics) {

    try {
      Map<String, List<TAuthMetric>> ruleMap = new HashMap<String, List<TAuthMetric>>();
      for (TAuthMetric metric : authMetrics) {
        List<TAuthMetric> metrics = null;
        String key = metric.getAuthProduct() + "#" + metric.getAuthDimension();
        if (ruleMap.containsKey(key) && CollectionUtils.isNotEmpty(ruleMap.get(key))) {
          metrics = ruleMap.get(key);
        } else {
          metrics = new ArrayList<TAuthMetric>();
        }
        metrics.add(metric);
        ruleMap.put(key, metrics);
      }
      TAuthMetric ageChcekResult = AuthCheckUtils
          .getAuthResult(model, CertCardConstant.AGE, ruleMap);
      TAuthMetric areaChcekResult = AuthCheckUtils
          .getAuthResult(model, CertCardConstant.AREA_CODE, ruleMap);
//      logger.info("ageChcekResult,{}",JSON.toJSONString(ageChcekResult));
      if (null != ageChcekResult
          && ageChcekResult.getAuthPass() == AuthConstant.CHECK_SUCCESS) {
        model.setAgeCheck(true);
      } else {
        model.setAgeCheck(false);
        model.setCheckMsg(ageChcekResult.getFailRemark());
        return;
      }

//      logger.info("areaChcekResult,{}",JSON.toJSONString(areaChcekResult));
      if (null != areaChcekResult) {
        if (areaChcekResult.getAuthPass() == AuthConstant.CHECK_SUCCESS) {
          model.setAgeCheck(true);
        } else {
          model.setAgeCheck(false);
          model.setCheckMsg(areaChcekResult.getFailRemark());
        }
      } else {
        model.setAreaCheck(true);
      }

    } catch (Exception e) {
      e.printStackTrace();
      logger.error("实名认证失败! {}", e.getMessage());
    }
  }

}
